package com.yin.waimai.controller;

import com.yin.waimai.dto.DeliveryPersonDTO;
import com.yin.waimai.dto.OrderDTO;
import com.yin.waimai.enums.DeliveryPersonStatus;
import com.yin.waimai.enums.OrderStatus;
import com.yin.waimai.model.LogisticsTrace;
import com.yin.waimai.service.DeliveryPersonService;
import com.yin.waimai.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 配送员专用控制器
 */
@RestController
@RequestMapping("/api/v1/delivery")
public class DeliveryController {

    private static final Logger log = LoggerFactory.getLogger(DeliveryController.class);

    private final DeliveryPersonService deliveryPersonService;
    private final OrderService orderService;

    @Autowired
    public DeliveryController(DeliveryPersonService deliveryPersonService, OrderService orderService) {
        this.deliveryPersonService = deliveryPersonService;
        this.orderService = orderService;
    }

    /**
     * 获取当前登录的配送员信息
     */
    @GetMapping("/me")
    @PreAuthorize("hasRole('DELIVERY_PERSON')")
    public ResponseEntity<?> getCurrentDeliveryPerson(Principal principal) {
        log.info("REST request to get current delivery person info for user: {}", principal.getName());
        
        Optional<DeliveryPersonDTO> deliveryPersonOpt = deliveryPersonService.findByName(principal.getName());
        if (deliveryPersonOpt.isPresent()) {
            return ResponseEntity.ok(deliveryPersonOpt.get());
        } else {
            log.warn("Delivery person not found for user: {}", principal.getName());
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("未找到配送员信息");
        }
    }

    /**
     * 获取分配给当前配送员的订单列表
     */
    @GetMapping("/orders")
    @PreAuthorize("hasRole('DELIVERY_PERSON')")
    public ResponseEntity<?> getMyOrders(Principal principal) {
        log.info("REST request to get orders for delivery person: {}", principal.getName());
        
        Optional<DeliveryPersonDTO> deliveryPersonOpt = deliveryPersonService.findByName(principal.getName());
        if (deliveryPersonOpt.isEmpty()) {
            log.warn("Delivery person not found for user: {}", principal.getName());
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("未找到配送员信息");
        }
        
        String deliveryPersonId = deliveryPersonOpt.get().getId();
        List<OrderDTO> orders = orderService.getOrdersByDeliveryPersonId(deliveryPersonId);
        return ResponseEntity.ok(orders);
    }

    /**
     * 更新配送员状态
     */
    @PutMapping("/status")
    @PreAuthorize("hasRole('DELIVERY_PERSON')")
    public ResponseEntity<?> updateMyStatus(
            @RequestParam DeliveryPersonStatus status,
            Principal principal) {
        log.info("REST request to update status to {} for delivery person: {}", status, principal.getName());
        
        Optional<DeliveryPersonDTO> deliveryPersonOpt = deliveryPersonService.findByName(principal.getName());
        if (deliveryPersonOpt.isEmpty()) {
            log.warn("Delivery person not found for user: {}", principal.getName());
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("未找到配送员信息");
        }
        
        DeliveryPersonDTO updatedPerson = deliveryPersonService.updateStatus(
                deliveryPersonOpt.get().getId(), status);
        return ResponseEntity.ok(updatedPerson);
    }

    /**
     * 更新配送员位置
     */
    @PutMapping("/location")
    @PreAuthorize("hasRole('DELIVERY_PERSON')")
    public ResponseEntity<?> updateMyLocation(
            @RequestParam double longitude,
            @RequestParam double latitude,
            Principal principal) {
        log.info("REST request to update location to [{}, {}] for delivery person: {}", 
                longitude, latitude, principal.getName());
        
        Optional<DeliveryPersonDTO> deliveryPersonOpt = deliveryPersonService.findByName(principal.getName());
        if (deliveryPersonOpt.isEmpty()) {
            log.warn("Delivery person not found for user: {}", principal.getName());
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("未找到配送员信息");
        }
        
        DeliveryPersonDTO updatedPerson = deliveryPersonService.updateLocation(
                deliveryPersonOpt.get().getId(), longitude, latitude);
        return ResponseEntity.ok(updatedPerson);
    }

    /**
     * 更新订单状态
     */
    @PutMapping("/orders/{orderNumber}/status")
    @PreAuthorize("hasRole('DELIVERY_PERSON')")
    public ResponseEntity<?> updateOrderStatus(
            @PathVariable String orderNumber,
            @RequestParam OrderStatus newStatus,
            @RequestParam String location,
            @RequestParam String description,
            Principal principal) {
        log.info("REST request to update order {} status to {} by delivery person: {}", 
                orderNumber, newStatus, principal.getName());
        
        // 验证订单是否分配给当前配送员
        Optional<DeliveryPersonDTO> deliveryPersonOpt = deliveryPersonService.findByName(principal.getName());
        if (deliveryPersonOpt.isEmpty()) {
            log.warn("Delivery person not found for user: {}", principal.getName());
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("未找到配送员信息");
        }
        
        try {
            OrderDTO orderDTO = orderService.getOrderByOrderNumber(orderNumber);
            if (orderDTO == null) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body("订单未找到");
            }
            
            // 检查订单是否分配给当前配送员
            if (orderDTO.getDeliveryPersonId() == null || 
                    !orderDTO.getDeliveryPersonId().equals(deliveryPersonOpt.get().getId())) {
                log.warn("Order {} is not assigned to delivery person {}", orderNumber, principal.getName());
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body("无权更新此订单状态");
            }
            
            // 检查状态转换是否合法（配送员只能更新特定状态）
            if (!isValidStatusTransitionForDeliveryPerson(orderDTO.getStatus(), newStatus)) {
                log.warn("Invalid status transition from {} to {} for order {}", 
                        orderDTO.getStatus(), newStatus, orderNumber);
                return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                        .body("状态转换无效：" + orderDTO.getStatus() + " -> " + newStatus);
            }
            
            OrderDTO updatedOrder = orderService.updateOrderStatusAndAddTrace(
                    orderNumber, newStatus, principal.getName(), location, description);
            return ResponseEntity.ok(updatedOrder);
            
        } catch (Exception e) {
            log.error("Error updating order status: {}", e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("更新订单状态失败: " + e.getMessage());
        }
    }

    /**
     * 获取订单物流轨迹
     */
    @GetMapping("/orders/{orderNumber}/traces")
    @PreAuthorize("hasRole('DELIVERY_PERSON')")
    public ResponseEntity<?> getOrderTraces(
            @PathVariable String orderNumber,
            Principal principal) {
        log.info("REST request to get traces for order {} by delivery person: {}", 
                orderNumber, principal.getName());
        
        // 验证订单是否分配给当前配送员
        Optional<DeliveryPersonDTO> deliveryPersonOpt = deliveryPersonService.findByName(principal.getName());
        if (deliveryPersonOpt.isEmpty()) {
            log.warn("Delivery person not found for user: {}", principal.getName());
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("未找到配送员信息");
        }
        
        OrderDTO orderDTO = orderService.getOrderByOrderNumber(orderNumber);
        if (orderDTO == null) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("订单未找到");
        }
        
        // 检查订单是否分配给当前配送员
        if (orderDTO.getDeliveryPersonId() == null || 
                !orderDTO.getDeliveryPersonId().equals(deliveryPersonOpt.get().getId())) {
            log.warn("Order {} is not assigned to delivery person {}", orderNumber, principal.getName());
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body("无权查看此订单轨迹");
        }
        
        List<LogisticsTrace> traces = orderService.getLogisticsTracesByOrderNumber(orderNumber);
        return ResponseEntity.ok(traces);
    }
    
    /**
     * 判断配送员是否可以将订单从当前状态转换为新状态
     * 配送员只能进行特定的状态转换，例如：
     * - PENDING_COLLECTION -> COLLECTED（已取件）
     * - COLLECTED -> TRANSPORTING（运输中）
     * - TRANSPORTING -> OUT_FOR_DELIVERY（派送中）
     * - OUT_FOR_DELIVERY -> SIGNED（已签收）
     * - SIGNED -> COMPLETED（已完成）
     */
    private boolean isValidStatusTransitionForDeliveryPerson(OrderStatus currentStatus, OrderStatus newStatus) {
        switch (currentStatus) {
            case PENDING_COLLECTION:
                return newStatus == OrderStatus.COLLECTED;
            case COLLECTED:
                return newStatus == OrderStatus.TRANSPORTING;
            case TRANSPORTING:
                return newStatus == OrderStatus.OUT_FOR_DELIVERY;
            case OUT_FOR_DELIVERY:
                return newStatus == OrderStatus.SIGNED;
            case SIGNED:
                return newStatus == OrderStatus.COMPLETED;
            default:
                return false;
        }
    }

    /**
     * 配送员接单
     */
    @PostMapping("/orders/{orderNumber}/accept")
    @PreAuthorize("hasRole('DELIVERY_PERSON')")
    public ResponseEntity<?> acceptOrder(
            @PathVariable String orderNumber,
            Principal principal) {
        log.info("REST request to accept order {} by delivery person: {}", 
                orderNumber, principal.getName());
        
        Optional<DeliveryPersonDTO> deliveryPersonOpt = deliveryPersonService.findByName(principal.getName());
        if (deliveryPersonOpt.isEmpty()) {
            log.warn("Delivery person not found for user: {}", principal.getName());
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("未找到配送员信息");
        }
        
        try {
            OrderDTO updatedOrder = orderService.acceptOrder(
                    orderNumber,
                    deliveryPersonOpt.get().getId(),
                    principal.getName()
            );
            return ResponseEntity.ok(updatedOrder);
        } catch (IllegalArgumentException e) {
            log.warn("Failed to accept order {} by delivery person {}: {}", 
                    orderNumber, principal.getName(), e.getMessage());
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
        } catch (Exception e) {
            log.error("Error accepting order {} by delivery person {}: {}", 
                    orderNumber, principal.getName(), e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("接单失败: " + e.getMessage());
        }
    }

    /**
     * 获取可接单的订单列表
     */
    @GetMapping("/available-orders")
    @PreAuthorize("hasRole('DELIVERY_PERSON')")
    public ResponseEntity<?> getAvailableOrders() {
        log.info("REST request to get available orders for delivery persons");
        
        List<OrderDTO> orders = orderService.getAvailableOrders();
        return ResponseEntity.ok(orders);
    }

    /**
     * 获取当前配送员的工作统计数据
     */
    @GetMapping("/statistics")
    @PreAuthorize("hasRole('DELIVERY_PERSON')")
    public ResponseEntity<?> getDeliveryStatistics(Principal principal) {
        log.info("REST request to get delivery statistics for user: {}", principal.getName());
        
        Optional<DeliveryPersonDTO> deliveryPersonOpt = deliveryPersonService.findByName(principal.getName());
        if (deliveryPersonOpt.isEmpty()) {
            log.warn("Delivery person not found for user: {}", principal.getName());
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("未找到配送员信息");
        }
        
        String deliveryPersonId = deliveryPersonOpt.get().getId();
        List<OrderDTO> orders = orderService.getOrdersByDeliveryPersonId(deliveryPersonId);
        
        // 计算统计数据
        Map<String, Object> statistics = new HashMap<>();
        
        // 总订单数
        statistics.put("totalOrders", orders.size());
        
        // 按状态统计订单数量
        Map<OrderStatus, Long> ordersByStatus = orders.stream()
                .collect(Collectors.groupingBy(OrderDTO::getStatus, Collectors.counting()));
        statistics.put("ordersByStatus", ordersByStatus);
        
        // 已完成订单数
        long completedOrders = orders.stream()
                .filter(order -> order.getStatus() == OrderStatus.COMPLETED || order.getStatus() == OrderStatus.SIGNED)
                .count();
        statistics.put("completedOrders", completedOrders);
        
        // 计算完成率
        double completionRate = orders.isEmpty() ? 0 : (double) completedOrders / orders.size() * 100;
        statistics.put("completionRate", Math.round(completionRate * 100) / 100.0); // 保留两位小数
        
        // 今日订单数
        LocalDate today = LocalDate.now();
        long todayOrders = orders.stream()
                .filter(order -> order.getCreationTime() != null && 
                        order.getCreationTime().toLocalDate().equals(today))
                .count();
        statistics.put("todayOrders", todayOrders);
        
        // 今日完成订单数
        long todayCompletedOrders = orders.stream()
                .filter(order -> order.getStatus() == OrderStatus.COMPLETED || order.getStatus() == OrderStatus.SIGNED)
                .filter(order -> order.getDeliveryTime() != null && 
                        order.getDeliveryTime().toLocalDate().equals(today))
                .count();
        statistics.put("todayCompletedOrders", todayCompletedOrders);
        
        return ResponseEntity.ok(statistics);
    }
}